<template>
  <view class="auth-form">
    <uni-forms ref="formRef" :model="formData" :rules="rules">
      <uni-forms-item 
        v-for="(item, index) in formItems" 
        :key="index" 
        :name="item.name" 
        :label="item.label"
        :label-width="80"
      >
        <template v-if="item.type === 'text' || item.type === 'password'">
          <uni-easyinput 
            :type="item.type" 
            v-model="formData[item.name]" 
            :placeholder="item.placeholder"
            :passwordIcon="item.type === 'password'"
          />
          <view class="extra-action" v-if="item.extra">
            <button 
              v-if="item.extra.type === 'code'" 
              class="code-btn" 
              :disabled="codeDisabled"
              @click="handleExtraClick(item)"
            >
              {{ codeBtnText }}
            </button>
          </view>
        </template>
      </uni-forms-item>
    </uni-forms>

    <slot name="extra"></slot>

    <button class="submit-btn" @click="handleSubmit">{{ submitText }}</button>

    <view class="nav-link" v-if="showNav">
      <text @click="handleNavClick">{{ navText }}</text>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, reactive, watch, onBeforeUnmount } from 'vue';

const props = defineProps({
  formItems: {
    type: Array,
    required: true,
    default: () => []
  },
  submitText: {
    type: String,
    default: '提交'
  },
  showNav: {
    type: Boolean,
    default: true
  },
  navText: {
    type: String,
    default: '已有账号？去登录'
  }
});

const emit = defineEmits(['submit', 'navigate', 'extra-click']);

const formRef = ref(null);
const formData = reactive({});
const codeDisabled = ref(false);
const countdown = ref(0);
let timer = null;

// 初始化表单数据
props.formItems.forEach(item => {
  formData[item.name] = '';
});

// 生成验证规则
const rules = computed(() => {
  const rules = {};
  props.formItems.forEach(item => {
    if (item.rules) {
      rules[item.name] = item.rules.map(rule => {
        if (rule.validator) {
          return {
            ...rule,
            validate: (value, callback) => {
              try {
                rule.validator(rule, value, callback, formData);
              } catch (error) {
                callback(new Error('验证失败'));
              }
            }
          };
        }
        return rule;
      });
    }
  });
  return rules;
});

// 验证码按钮文本
const codeBtnText = computed(() => {
  return countdown.value > 0 ? `${countdown.value}s后重试` : '获取验证码';
});

// 处理验证码点击
function handleExtraClick(item) {
  formRef.value.validateField([item.name]).then(res => {
    countdown.value = 60;
    codeDisabled.value = true;
    
    timer = setInterval(() => {
      countdown.value--;
      if (countdown.value <= 0) {
        clearInterval(timer);
        codeDisabled.value = false;
      }
    }, 1000);
    
    emit('extra-click', item);
  }).catch(err => {
    console.log('验证失败', err);
  });
}

// 提交表单
function handleSubmit() {
  formRef.value.validate().then(res => {
    emit('submit', formData);
  }).catch(err => {
    console.log('表单验证失败', err);
  });
}

// 导航点击
function handleNavClick() {
  emit('navigate');
}

// 清除定时器
onBeforeUnmount(() => {
  if (timer) clearInterval(timer);
});
</script>

<style lang="scss" scoped>
.auth-form {
  .uni-forms-item {
    margin-bottom: 40rpx;
    
    :deep(.uni-forms-item__label) {
      font-size: $font-size-28rpx;
      color: $text-color;
    }
    
    :deep(.uni-easyinput__content) {
      border-radius: 10rpx;
    }
  }
  
  .extra-action {
    position: absolute;
    right: 0;
    top: 0;
    height: 100%;
    display: flex;
    align-items: center;
    
    .code-btn {
      background-color: $primary-color;
      color: $text-color-inverse;
      border: none;
      border-radius: 50rpx;
      padding: 0 30rpx;
      height: 60rpx;
      line-height: 60rpx;
      font-size: $font-size-24rpx;
      
      &[disabled] {
        background-color: #ccc;
      }
      
      &::after {
        border: none;
      }
    }
  }
  
  .submit-btn {
    background-color: $primary-color;
    color: $text-color-inverse;
    border: none;
    border-radius: 50rpx;
    height: 90rpx;
    line-height: 90rpx;
    font-size: $font-size-32rpx;
    margin-top: 20rpx;
    
    &::after {
      border: none;
    }
  }
  
  .nav-link {
    text-align: center;
    margin-top: 40rpx;
    
    text {
      color: $primary-color;
      font-size: $font-size-26rpx;
    }
  }
}
</style>